package com.vpen.server.server;

import com.vpen.server.handler.ServerChannelInitializerImpl;
import com.vpen.server.http.HttpChannelInitializerImpl;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 描述
 *
 * @author 韦鹏
 * @date 2024/4/5 22:37
 */
@Slf4j
@Component
public class HttpServer {
    @Autowired
    private HttpChannelInitializerImpl channelInitializer;


    private final int port = 8090;
    /**
     * 引导服务
     */
    private final ServerBootstrap serverBootstrap = new ServerBootstrap();

    /**
     * boss
     */
    private final EventLoopGroup bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("http-BOSS-GROUP", true));
    /**
     * worker
     */
    private final EventLoopGroup workerGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("http-WORKER-GROUP", false));


    @PostConstruct
    private void init() {
        start();
    }

    @PreDestroy
    private void destroy() {
        this.shutdown();
    }


    private void start() {
        serverBootstrap
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .localAddress(port)
                .option(ChannelOption.SO_BACKLOG, 128) // 默认值为50，用于构造服务端套接字ServerSocket对象，标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度。
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) // 探测连接是否存活，若不存活，则关闭连接，释放资源。
                .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE) // TCP为减少交互次数，会将数据积累起来一起发送，会有一定延迟；低延迟，需启用该选项。
                .childHandler(channelInitializer)
                .bind()
                .syncUninterruptibly()
                .addListener((ChannelFutureListener) channelFuture -> {
                    if (channelFuture.isSuccess()) {
                        log.info("服务启动：{}", port);
                    } else {
                        channelFuture.cause().printStackTrace();
                        log.warn("");
                    }
                })
                .channel()
                .closeFuture();
    }


    private void shutdown() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
        log.info("========== netty server shutdown! ==========");
    }
}
